let rec apply_new_env ( env_list, f_name, x_name, d_val) = match env_list with
	| hd::tail -> if (fst(hd) = f_name) 
											then ((f_name), bind (snd(hd)) x_name d_val) :: tail
											else hd :: (apply_new_env ( tail , f_name, x_name, d_val))														 
	| [] -> [] ;;

let rec update_env_list (fun_list, env_list, x_name, d_val) = match fun_list with
	| hd::tail ->  apply_new_env ( env_list, hd, x_name, d_val)
	| _ -> env_list
	;; 	 


(* Valutazione delle dichiarazioni *)
let rec close_dec d (rho,l, env_list, fun_list) = match d with
		Empty -> (rho,l, env_list,fun_list) 
	| Const(t, x, v) -> ( (bind rho x 	(DConst (t, v))), l, update_env_list (fun_list, env_list, x, (DConst (t, v))), fun_list) 
	| Var (t, x) -> ( (bind rho x 	(DVar (t, l))), l+1, update_env_list (fun_list, env_list, x, (DVar (t, l))), fun_list)
	| Init (t, x, e) -> ( (bind rho x 	(DVar (t, l))), l+1, update_env_list (fun_list, env_list, x, (DVar (t, l))), fun_list)
	| Array (t, x, v) -> ( (bind rho x 	( DArray (t, v, l) )), l+v, update_env_list (fun_list, env_list, x, ( DArray (t, v, l) ) ), fun_list) 
	| Function (in_t, name, tcall, out_t, param_name, body, ret) ->
		let rho' = bind rho name 	(DFunc(tcall, in_t, out_t, param_name, body, ret)) in(
			(rho', l, 	(name, rho') :: env_list,	name :: fun_list))			
	| Dseq(d1, d2) -> close_dec d2 (close_dec d1 (rho,l, env_list, fun_list))
;;

let rec close_block block (rho,l, env_list) = match block with
	| BlockSeq(b1, b2) -> let (rho',l',env_list')= close_block b1(rho,l, env_list) in(
																				close_block b1(rho,l, env_list'))
	| DecBlock (dec, b1) -> let (rho',l',env_list', fun_list') = close_dec dec (rho,l, env_list, []) in(
																					close_block b1(rho',l', env_list'))
	| Com (com) -> (rho,l,env_list)
;;

let pre_processer (Program(d,b1)) = 
	let (rho, limit, env_list, fun_list) =  close_dec d ((emptyenv()), 0, [], []) in
	  close_block b1 (rho, limit, env_list);;

let rec get_env env_list f_name = match env_list with
	| hd::tail -> if  (fst(hd)=f_name) then snd(hd) else get_env tail f_name 
	| _ -> raise (DEBUG ("ma non doveva restituire un ambiente vuoto by Stefano"));;
